<?php
/*
 * Copyright 2010 Johannes M. Schmitt
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Build configuration for a specific app. This class has all the configuration
 * options that GoogleClosureCompiler has, and additionally some options which
 * are specifically used for our build process, and not by the compiler itself.
 * 
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class GoogleClosureCompilerConfiguration
{
	/**
	 * The class that is your entry point to the application
	 * @var string
	 */
  private $_entryPointClass;
  
  /**
   * The languages to compile the application for
   * @var array
   */
  private $_locales;
  
  /**
   * The user agents to compile the application for. If you do not supply any
   * user agents, then all browser dependent code is left intact, and no browser
   * specific optimizations are made.
   * 
   * @var array
   */
  private $_userAgents;
  
  /**
   * The format to use for output files.
   * @var string
   */
  private $_outputFormat = '%appName%_%locale%_%userAgent%.js';
  
  /**
   * The path were all output files should be stored
   * @var string
   */
  private $_outputPath;
  
  /**
   * Additional settings to pass to the compiler
   * @var array
   */
  private $_compilerSettings;
  
  /**
   * The CSS Renaming map to use
   * @var GoogleClosureCSSRenamingMap
   */
  private $_cssRenamingMap;
  
  /**
   * The dependency tree
   * @var GoogleClosureDependencies
   */
  private $_dependencies;
  
  /**
   * @param string $depsFile
   * @param string $outputPath
   * @param string $entryPointClass
   * @param array $locales
   * @param array $userAgents
   */
  public function __construct($depsFile, $outputPath, $entryPointClass, 
    array $locales, array $userAgents = array()
  )
  {
    $this->_dependencies = GoogleClosureDependencies::fromFile($depsFile);
  	$this->_outputPath = $outputPath;
    $this->_entryPointClass = $entryPointClass;
    $this->_locales = $locales;
		$this->_userAgents = $userAgents;
    $this->_compilerSettings = array();
  } 
  
  /**
   * The languages to compile the application for
   * @return array
   */
  public final function getLocales()
  {
    return $this->_locales;
  }
  
  /**
   * The class that represents the app entry point
   * @return string
   */
  public final function getEntryPointClass()
  {
    return $this->_entryPointClass;
  }
  
  /**
   * Returns the user agents
   * @return array
   */
  public final function getUserAgents()
  {
  	return $this->_userAgents;
  }
  
  /**
   * Sets the output format for compiled files
   * @param string $format
   */
  public final function setOutputFormat($format)
  {
  	$this->_outputFormat = $format;
  }
  
  /**
   * Returns the output format to use
   * @return string
   */
  public final function getOutputFormat()
  {
  	return $this->_outputFormat;
  }
  
  /**
   * Returns settings to be applied to the compiler instance
   * @return array
   */
  public final function getCompilerSettings()
  {
  	return $this->_compilerSettings;
  }
  
  public final function getOutputPath()
  {
  	return $this->_outputPath;
  }
  
  /**
   * Alias for callOnCompiler(). Usually you do not need to call 'callOnCompiler'
   * directly except for methods which exist on GoogleClosureCompilerConfiguration
   * and on GoogleClosureCompiler. In these cases, the method on the configuration
   * class will have precedence.
   * 
   * @see callOnCompiler($method, $arguments)
   * @param string $method
   * @param array $arguments
   * @return GoogleClosureCompilerConfiguration
   */
  public function __call($method, $arguments)
  {
  	return $this->callOnCompiler($method, $arguments);
  }
  
  /**
   * Enable the user to call any public method that he could call on a compiler
   * instance, and record it; so, we can perform the call on the actual compiler 
   * instance once it has been created.
   * 
   * @param string $method
   * @param array $arguments
   * @return GoogleClosureCompilerConfiguration The configuration instance itself
   */
  public function callOnCompiler($method, $arguments)
  {
  	$reflection = new ReflectionClass('GoogleClosureCompiler');
  	if (!$reflection->hasMethod($method))
  		throw new RuntimeException(sprintf('The method "%s" does neither exist '
  			.'on GoogleClosureCompilerConfiguration nor on GoogleClosureCompiler.',
  			$method));
  			
  	$reflectionMethod = $reflection->getMethod($method);
  	if (!$reflectionMethod->isPublic())
  		throw new RuntimeException(sprintf('The method "%s" is not declared '
  			.'public on GoogleClosureCompiler.', $method));
  			
  	$this->_compilerSettings[$method][] = $arguments;
  	
  	return $this;
  }
  
  /**
   * @param GoogleClosureCSSRenamingMap $map
   */
  public final function setCSSRenamingMap(GoogleClosureCSSRenamingMap $map)
  {
  	$this->_cssRenamingMap = $map;
  }
  
  /**
   * @return GoogleClosureCSSRenamingMap
   */
  public final function getCSSRenamingMap()
  {
  	return $this->_cssRenamingMap;
  }
  
  public final function getDependencies()
  {
  	return $this->_dependencies;
  }
}